package dao

import (
	"errors"
	"fmt"
	"gorm.io/gorm"
	"log"
	"strings"
	"time"
	"yundian/internel/app/helper"
	"yundian/internel/app/helper/request"
	"yundian/internel/app/models/placemodel"
	"yundian/internel/app/models/profit"
	"yundian/internel/app/models/smscode"
	"yundian/internel/app/models/users"
	"yundian/internel/pkg/dingo"
	"yundian/internel/pkg/dingo/global"
	"yundian/internel/pkg/utils"
)

// -------------------- dao层 - 后台管理员、代理商帐号相关操作 -----------------------//

type UserDao struct {
}

func NewUserDao() *UserDao {
	return &UserDao{}
}

func (d *UserDao) GetWifiUserInfoByMemberId(memberId int) *dingo.ErrorWrap {
	dbInfo := &users.WifiUserDb{}

	db := global.Orm.Where(`member_id=?`, memberId)

	db.Find(&dbInfo)
	return dingo.ErrorIf(db.Error, dbInfo)
}

// GetUserInfoByMemberId 获取用户详情
func (d *UserDao) GetUserInfoByMemberId(memberId int) *dingo.ErrorWrap {
	dbInfo := &users.UserModel{}

	db := global.Orm.Table(`members m`).Select(`u.*`)
	db.Joins(`LEFT JOIN users u ON m.phone=u.phone`)
	db.Where(`m.id=? AND u.id>0`, memberId)

	db.Find(&dbInfo)
	return dingo.ErrorIf(db.Error, dbInfo)
}

// 获取用户下级列表
func (d *UserDao) GetUserListByParentId(parentId int) *dingo.ErrorWrap {

	lst := make([]*users.UserInfoWithAgent, 0)
	sql := `select u.*,r.name as role_name from users u left join roles r on r.id = u.role_id where
u.parent_id = ? and u.is_admin != 4 and u.is_place != 3 and u.is_delete = 0`
	db := global.Orm.Debug().Raw(sql, parentId).Find(&lst)

	return dingo.ErrorIf(db.Error, lst)
}

// 获取用户下级列表
func (d *UserDao) GetAllIsAdminUserListByParentId(parentId int, isAdmin uint8) *dingo.ErrorWrap {

	lst := make([]*users.UserInfoWithAgent, 0)
	isAdminSql := `  and (u.is_admin =? or u.is_admin = 3 ) `
	if isAdmin == 0 {
		isAdminSql = ` `
	}
	sql := `select u.*,r.name as role_name from users u left join roles r on r.id = u.role_id where
u.parent_id = ?  ` + isAdminSql + `  and  u.is_delete = 0`
	db := global.Orm.Debug().Raw(sql, parentId, isAdmin).Find(&lst)

	return dingo.ErrorIf(db.Error, lst)
}

// 获取用户下级列表
func (d *UserDao) GetAllIsAdminUserListByParentIds(parentIds []int, isAdmin uint8) *dingo.ErrorWrap {
	lst := make([]*users.UserInfoWithAgent, 0)

	sql := `select u.*,r.name as role_name from users u left join roles r on r.id = u.role_id where u.parent_id in (?)  and  u.is_delete = 0`
	db := global.Orm.Debug().Raw(sql, parentIds).Find(&lst)

	return dingo.ErrorIf(db.Error, lst)
}

//获取所有用户列表
func (d *UserDao) GetUserListByArrParentId(param *request.UserList) *dingo.ErrorWrap {

	var (
		lst    []*users.UserInfoWithAgent
		count  int64
		limit  int = param.PageSize
		offset int = param.PageSize * (param.PageNo - 1)
	)
	//	sql := `select u.*,r.name as role_name from users u left join roles r on r.id = u.role_id where
	//u.parent_id = ? and u.is_admin != 4 and u.is_place != 3 and u.is_delete = 0`
	//	db := global.Orm.Debug().Raw(sql, param.UserId).Find(&lst)
	db := global.Orm.Debug().Table("users u").
		Select("u.*,r.name as role_name").
		Joins("left join roles r on u.role_id = r.id").
		Where("u.parent_id = ?", param.UserId).
		Where("u.is_admin != 4 and u.is_place != 3 and u.is_delete = 0")
	db.Limit(limit).Offset(offset).Find(&lst).Limit(-1).Offset(-1).Count(&count)
	return dingo.ErrorIf(db.Error, lst, count)
}

func (d *UserDao) GetUserListByName(name string) *dingo.ErrorWrap {

	var lst []users.UserModel
	db := global.Orm.Debug().Table("users").
		Where("name like ?", fmt.Sprint("%", name, "%")).
		Order("id asc").Find(&lst)
	return dingo.ErrorIf(db.Error, lst)
}

func (d *UserDao) GetUserListByUserName(userName string, userId int) *dingo.ErrorWrap {
	m := make([]users.UserModel, 0)
	db := global.Orm.Debug().Table("users").Where("is_delete = 0")
	if userName != "" {
		nameSql := fmt.Sprint("%", userName, "%")
		db.Where("(name like ? or user_name like ?)", nameSql, nameSql)
	}
	if userId != 2 {
		userIdArr := NewUserDao().QueryChildUserIds(userId).Unwrap().([]int)
		db.Where("id in (?)", userIdArr)
	}
	db.Order("id asc").Limit(20).Find(&m)
	return dingo.ErrorIf(db.Error, m)
}

func (d *UserDao) GetUserAllListByName(userName string, userId int, IsAdmin uint8) *dingo.ErrorWrap {
	isAdmins := []int{
		helper.TypeNumIsAdminOperator,
		helper.TypeNumIsAdminBranch,
		helper.TypeNumIsAdminKaProject,
		helper.TypeNumIsAdminRegion,
		helper.TypeNumIsAdminResource,
		helper.TypeNumIsAdminPartner,
	}
	m := make([]users.UserModel, 0)
	db := global.Orm.Debug().
		Table("users").
		Where("is_delete = 0 and is_admin in (?)", isAdmins)

	if userName != "" {
		nameSql := fmt.Sprint("%", userName, "%")
		db.Where("(name like ? or user_name like ?)", nameSql, nameSql)
	}

	if userId != 2 { // userId为 2 时  取所有，这样就不用递归查询运营商下的所有用户了，也不需要使用 in 条件了
		userIdArr := NewUserDao().QueryChildUserIds(userId).Unwrap().([]int) // 查询用户ID下所有下级用户ID
		db.Where("id in (?)", userIdArr)
	}

	db.Order("is_admin,id asc").Limit(20).Find(&m)

	return dingo.ErrorIf(db.Error, m)
	//var lst []users.UserModel
	//db := global.Orm.Debug().Table("users")
	//
	//if IsAdmin != helper.TypeNumIsAdminOperator {
	//	userIdArr := NewUserDao().QueryChildUserIds(userId).Unwrap().([]int)
	//	db.Where("id in (?)", userIdArr)
	//}
	//db.Where("is_admin IN (?)", []int{helper.TypeNumIsAdminMerchant, helper.TypeNumIsAdminBranch,
	//	helper.TypeNumIsAdminKaProject, helper.TypeNumIsAdminRegion, helper.TypeNumIsAdminResource})
	//
	//db.Where("name like ?", fmt.Sprint("%", name, "%"))
	//
	//db.Order("id asc").Limit(20).Find(&lst)
	//return dingo.ErrorIf(db.Error, lst)
}

// GetUserList 获取后台用户列表
func (d *UserDao) GetUserList(param *request.UserList) *dingo.ErrorWrap {

	var (
		lst    []users.AdminUser
		count  int64
		limit  int = param.PageSize
		offset int = param.PageSize * (param.PageNo - 1)
	)

	db := global.Orm.
		Table("users u").
		Select("u.*,r.name as role_name").
		Joins("left join roles r on u.role_id = r.id")

	db.Where("u.is_delete = 0") // 未删除

	if param.SearchText != "" {
		db.Where("u.name like ?", fmt.Sprint("%", param.SearchText, "%"))
		//db.Where("concat(user_name,real_name) like ?", fmt.Sprint("%", param.SearchText, "%"))
	}
	if param.Phone != "" {
		db.Where("u.phone = ?", param.Phone)
	}
	if param.RoleId > 0 {
		db.Where("r.id = ?", param.RoleId)
	}
	if param.Status > 0 {
		db.Where("u.status = ?", param.Status)
	}
	if param.IsAdmin > 0 {
		db.Where("u.is_admin = ?", param.IsAdmin)
	}
	if param.ParentId > 0 {
		db.Where("u.parent_id = ?", param.ParentId)
	}

	// 时间查询
	if param.BeginTime != "" {
		beginTime := strings.Split(param.BeginTime, ",")
		db.Where("u.last_login_time >= ? and u.last_login_time <= ?", beginTime[0], beginTime[1])
	}

	// 排序
	if param.SortField != "" && param.SortOrder == "ascend" {
		db.Order(fmt.Sprintf("u.%s asc", utils.String(param.SortField).SnakeCase()))
	}
	if param.SortField != "" && param.SortOrder == "descend" {
		db.Order(fmt.Sprintf("u.%s desc", utils.String(param.SortField).SnakeCase()))
	}
	if param.SortField == "" {
		db.Order("u.last_login_time desc, u.create_at desc")
	}

	db.Limit(limit).Offset(offset).Find(&lst).Limit(-1).Offset(-1).Count(&count)

	return dingo.ErrorIf(db.Error, lst, count)

}

func (d *UserDao) GetAgentUserListById(id int) *dingo.ErrorWrap {
	m := &users.UserInfoWithAgent{}
	sql := "select * from users where id = ?"
	db := global.Orm.Debug().Raw(sql, id).Find(&m)

	return dingo.ErrorIf(db.Error, m)
}

// GetPlaceLevelCount 获取同等级的商户数量
func (d *UserDao) GetPlaceLevelCount(level string, loginUserId int, isAdmin, isPlace uint8) *dingo.ErrorWrap {
	var count int64
	db := global.Orm.Debug().Table("places p").Where("level = ?", level)

	// 代理商用户
	//if isAdmin == helper.TypeNumIsAdminAgent && isPlace != helper.TypeNumIsPlaceKa {
	//	userIdArr := d.QueryChildUserIds(loginUserId).Unwrap().([]int)
	//	userIdArr = append(userIdArr, loginUserId)
	//	placeModelLst := NewPlaceDao().GetPlaceByParentIds(userIdArr).Unwrap().([]*placemodel.PlaceModel)
	//	placeIdArr := make([]int, 0)
	//	for _, placeModel := range placeModelLst {
	//		placeIdArr = append(placeIdArr, placeModel.Id)
	//	}
	//	db.Where("p.id in ?", placeIdArr)
	//}
	if isAdmin > helper.TypeNumIsAdminStaff {
		userIdArr := d.QueryChildUserIds(loginUserId).Unwrap().([]int)
		userIdArr = append(userIdArr, loginUserId)
		placeModelLst := NewPlaceDao().GetPlaceByParentIds(userIdArr).Unwrap().([]*placemodel.PlaceModel)
		placeIdArr := make([]int, 0)
		for _, placeModel := range placeModelLst {
			placeIdArr = append(placeIdArr, placeModel.Id)
		}
		db.Where("p.id in ?", placeIdArr)
	}

	// 分公司用户
	if isPlace == helper.TypeNumIsAdminBranch {
		childUserIds := NewUserDao().QueryChildUserIds(loginUserId).Unwrap().([]int)
		placesIdArr := NewUserDao().GetPlacesIds(loginUserId, childUserIds).Unwrap().([]int)
		db.Where("p.id in ?", placesIdArr)
	}

	db.Count(&count)
	//sql := `select count(1) as count from places where level = ?`
	//db := global.Orm.Raw(sql, level).Find(&count)
	return dingo.ErrorIf(db.Error, count)
}

// InsertUser 新增用户
func (d *UserDao) InsertUser(param *request.AdminUserInsertReq) *dingo.ErrorWrap {
	m := users.New().Mutate(
		users.WithCreateAt(dingo.Time(time.Now().Unix())),
		users.WithName(param.Name),
		users.WithPhone(param.Phone),
		users.WithStatus(param.Status),
		users.WithPassword(utils.EncryptPassword(param.Password)),
		users.WithRoleId(param.RoleId),
		users.WithParentId(param.ParentId),
		users.WithIsAdmin(param.IsAdmin),
		users.WithProfitType(param.ProfitType),
		users.WithProfitProportion(param.ProfitProportion),
	)
	db := global.Orm.Table("users").
		Select("create_at", "name", "phone", "status", "password", "role_id", "is_admin", "parent_id").
		Create(m)
	return dingo.ErrorIf(db.Error, true)
}

//func (d *UserDao) InsertPlaceUser(param *request.AdminUserInsertReq) *dingo.ErrorWrap {
//	db := global.Orm
//	p := placemodel.NewPlaceModel()
//	err := db.Transaction(func(tx *gorm.DB) error {
//		m := users.New().Mutate(
//			users.WithCreateAt(dingo.Time(time.Now().Unix())),
//			users.WithName(param.Name),
//			users.WithNickName(param.PlaceName),
//			users.WithUserName(param.Name),
//			users.WithPhone(param.Phone),
//			users.WithPhoneCode("+86"),
//			users.WithStatus(param.Status),
//			users.WithPassword(param.Password),
//			users.WithRoleId(param.RoleId),
//			users.WithParentId(param.ParentId),
//			users.WithIsAdmin(param.IsAdmin),
//			users.WithProfitType(param.ProfitType),
//			users.WithProfitIsVisible(param.ProfitIsVisible),
//			users.WithProfitProportion(param.ProfitProportion),
//			users.WithIsPlace(1),
//			users.WithUserNo("SH"+time.Now().Format("20060102150405")),
//		)
//		if err := tx.Debug().Table("users").Create(&m).Error; err != nil {
//			// 返回任何错误都会回滚事务
//			return err
//		}
//		// 终极上级
//		uInfo := NewUserDao().GetUserInfoById(param.ParentId).Unwrap().(*users.UserModel)
//		userInfo := GetParentUserInfoById(uInfo)
//		var entryStatus int8 // 1进场中 2进场结束
//		if param.EntryMoney > 10 && param.EntryAt > 0 {
//			entryStatus = 1
//		} else {
//			entryStatus = 0
//		}
//
//		p.Mutate(
//			places.WithCreateAt(dingo.Time(time.Now().Unix())),
//			places.WithPlaceName(param.PlaceName),
//			places.WithClassName(param.ClassName),
//			places.WithUserID(m.ID),
//			places.WithUserName(m.UserName),
//			places.WithLevel("E"),
//			places.WithStatus(2),
//			places.WithMaintainerId(param.MaintainerId),
//			places.WithProvince(param.Province),
//			places.WithCity(param.City),
//			places.WithCountry(param.County),
//			places.WithAddress(param.Address),
//			places.WithRegionIds(param.RegionIds),
//			places.WithEntryMoney(param.EntryMoney),
//			places.WithAgentUserId(userInfo.ID),
//			places.WithAgentUserName(userInfo.Name),
//			places.WithEntryAt(dingo.Time(param.EntryAt)),
//			places.WithEntryStatus(entryStatus),
//		)
//
//		if err := tx.Debug().Table("places").Create(&p).Error; err != nil {
//			return err
//		}
//		// 返回 nil 提交事务
//		return nil
//	})
//	//log.Println("当前id是:",p.Id,p.PlaceName)
//	return dingo.ErrorIf(err, p)
//
//}

// GetUserIdByPid 获取某个用户下的所有代理商用户ID
func (d *UserDao) GetUserIdByPid(pid []int) *dingo.ErrorWrap {
	//userModelLst := make([]*users.UserModel, 0)
	userIdArr := make([]int, 0)
	sql := "select id from users where parent_id in ?"
	db := global.Orm.Raw(sql, pid).Find(&userIdArr)

	//log.Print("获取某个用户下的所有代理商用户的SQL为：", sql)
	//userIdArr := make([]int, len(userModelLst))
	//for _, userModel := range userModelLst {
	//	userIdArr = append(userIdArr, userModel.ID)
	//}
	return dingo.ErrorIf(db.Error, userIdArr)
}

func (d *UserDao) GetUserIdByParentId(pid []int) *dingo.ErrorWrap {
	userModelLst := make([]*users.UserInfoWithPlace, 0)
	//userIdArr := make([]int, 0)
	sql := "select * from users where parent_id in (?) and is_place != 1"
	db := global.Orm.Raw(sql, pid).Find(&userModelLst)

	//log.Print("获取某个用户下的所有代理商用户的SQL为：", sql)
	//userIdArr := make([]int, len(userModelLst))
	//for _, userModel := range userModelLst {
	//	userIdArr = append(userIdArr, userModel.ID)
	//}
	return dingo.ErrorIf(db.Error, userModelLst)
}

// GetUserByPlaceIdAnd 获取某个用户下的所有代理商用户ID
func (d *UserDao) GetUserByPlaceIdAnd(placeId int) *dingo.ErrorWrap {
	userModel := users.New()
	sql := "select u.* from places p LEFT JOIN users u on p.user_id = u.id WHERE p.id = ?"
	db := global.Orm.Debug().Raw(sql, placeId).Find(&userModel)
	return dingo.ErrorIf(db.Error, userModel)
}

// GetUserByPlaceId 获取某个用户下的所有代理商用户ID
func (d *UserDao) GetUserByPlaceId(placeId int) *dingo.ErrorWrap {
	userModel := users.New()
	sql := "select u.* from places p LEFT JOIN users u on p.user_id = u.id WHERE p.id = ?"
	db := global.Orm.Debug().Raw(sql, placeId).Find(&userModel)
	return dingo.ErrorIf(db.Error, userModel)
}

// GetAllAgentUserList 获取代理商
func (d *UserDao) GetAllAgentUserList(userName string) *dingo.ErrorWrap {
	fmt.Println("GetAllAgentUserList:")
	m := make([]*users.UserModel, 0)
	db := global.Orm.Debug().
		Table("users").
		Where("is_delete = 0 and is_place = 0 and is_admin > 4")

	if userName != "" {
		db.Where("name like ?", fmt.Sprint("%", userName, "%"))
	}
	// 运营商、代理商登录，添加商户上级只能是自己，
	//if isAdmin == 2 || isAdmin == 3 {
	//	db.Where("id = ?", loginUserId)
	//} else {
	//	// 员工 登录上级只能是自己的上级
	//	db.Where("id = ?", parentId)
	//}
	db.Order("id asc").Find(&m)

	return dingo.ErrorIf(db.Error, m)
}

// GetAllAgentUserList 获取代理商
func (d *UserDao) GetAllAgentUserNoLoginUserList(userName string, userId int) *dingo.ErrorWrap {
	isAdmins := []int{helper.TypeNumIsAdminOperator, helper.TypeNumIsAdminBranch, helper.TypeNumIsAdminKaProject, helper.TypeNumIsAdminRegion, helper.TypeNumIsAdminResource, helper.TypeNumIsAdminBd, helper.TypeNumIsAdminPartner}
	m := make([]*users.AgentUserList, 0)
	db := global.Orm.Debug().
		Table("users").
		Where("is_delete = 0 and is_admin in (?)", isAdmins)

	if userName != "" {
		nameSql := fmt.Sprint("%", userName, "%")
		db.Where("(name like ? or user_name like ?)", nameSql, nameSql)
	}

	if userId != 2 { // userId为 2 时  取所有，这样就不用递归查询运营商下的所有用户了，也不需要使用 in 条件了
		userIdArr := NewUserDao().QueryChildUserIds(userId).Unwrap().([]int) // 查询用户ID下所有下级用户ID
		db.Where("id in (?)", userIdArr)
	}

	db.Order("is_admin,id asc").Limit(20).Find(&m)

	return dingo.ErrorIf(db.Error, m)
}

// UpdateUser 更新代理商用户信息
func (d *UserDao) UpdateUser(param *request.AdminUserInsertReq) *dingo.ErrorWrap {
	m := users.New().Mutate(
		users.WithId(param.Id),
		users.WithUpdateAt(dingo.Time(time.Now().Unix())),
		users.WithName(param.Name),
		users.WithPhone(param.Phone),
		users.WithStatus(param.Status),
		users.WithPassword(param.Password),
		users.WithRoleId(param.RoleId),
		users.WithParentId(param.ParentId),
		users.WithIsAdmin(param.IsAdmin),
	)
	db := global.Orm.Table("users").Model(&m).
		Select("update_at", "name", "phone", "status", "role_id", "is_admin", "parent_id").
		Updates(m)
	return dingo.ErrorIf(db.Error, true)
}

//func (d *UserDao) UpdatePlaceUser(param *request.AdminUserInsertReq) *dingo.ErrorWrap {
//
//	err := global.Orm.Transaction(func(tx *gorm.DB) error {
//		placeInfo := placemodel.NewPlaceModel()
//		global.Orm.Table("places").Where("id = ?", param.Id).Find(placeInfo)
//		// 1. 新增代理商表
//		m := users.New().Mutate(
//			users.WithUpdateAt(dingo.Time(time.Now().Unix())),
//			users.WithName(param.Name),
//			users.WithNickName(param.PlaceName),
//			users.WithUserName(param.Name),
//			users.WithPhone(param.Phone),
//			users.WithStatus(param.Status),
//			users.WithPassword(param.Password),
//			users.WithRoleId(param.RoleId),
//			users.WithParentId(param.ParentId),
//			users.WithIsAdmin(param.IsAdmin),
//			users.WithProfitIsVisible(param.ProfitIsVisible),
//			users.WithProfitProportion(param.ProfitProportion),
//		)
//		tx.Debug().Table("users").Where("id = ?", placeInfo.UserID).Model(&m).Updates(m)
//		if err := tx.Error; err != nil {
//			// 返回任何错误都会回滚事务
//			return err
//		}
//
//		uInfo := NewUserDao().GetUserInfoByPlaceId(param.Id).Unwrap().(*users.UserModel)
//		userInfo := GetParentUserInfoById(uInfo)
//		var entryStatus int8 // 1进场中 2进场结束
//		if param.EntryMoney > 10 && param.EntryAt > 0 {
//			entryStatus = 1
//		} else {
//			entryStatus = 0
//		}
//		// 2. 修改商户表
//		placeInfo.UpdateAt = dingo.Time(time.Now().Unix())
//		placeInfo.PlaceName = param.PlaceName
//		placeInfo.ClassName = param.ClassName
//		placeInfo.MaintainerId = param.MaintainerId
//		placeInfo.Province = param.Province
//		placeInfo.City = param.City
//		placeInfo.Country = param.County
//		placeInfo.Address = param.Address
//		placeInfo.RegionIds = param.RegionIds
//		placeInfo.EntryMoney = param.EntryMoney
//		placeInfo.AgentUserId = userInfo.ID
//		placeInfo.AgentUserName = userInfo.Name
//		placeInfo.EntryAt = dingo.Time(param.EntryAt)
//		placeInfo.EntryStatus = entryStatus
//
//		tx.Debug().Table("places").
//			Select("update_at", "place_name", "class_name", "user_id",
//				"user_name", "maintainer_id", "province", "city", "", "country", "address",
//				"region_ids", "entry_money", "agent_user_id", "agent_user_name", "entry_at", "entry_status").
//			Where("id = ?", placeInfo.Id).
//			Model(&placeInfo).
//			Updates(placeInfo)
//
//		if err := tx.Error; err != nil {
//			// 返回任何错误都会回滚事务
//			return err
//		}
//
//		// 2. 修改设备表
//		d := devices.New().Mutate(
//			devices.WithUpdateAt(dingo.Time(time.Now().Unix())),
//			devices.WithPlaceName(param.PlaceName),
//		)
//
//		tx.Debug().Table("devices").Where("place_id = ?", placeInfo.Id).Model(&d).Updates(d)
//
//		if err := tx.Error; err != nil {
//			// 返回任何错误都会回滚事务
//			return err
//		}
//		// 返回 nil 提交事务
//		return nil
//	})
//
//	return dingo.ErrorIf(err, true)
//}

// UpdateUserStatus 更新代理商用户状态
func (d *UserDao) UpdateUserStatus(id int, status int8) *dingo.ErrorWrap {
	sql := "update users set status = ? where id = ?"
	db := global.Orm.Exec(sql, status, id)
	return dingo.ErrorIf(db.Error, true)
}

// UpdateUserPassword 更新代理商用户密码
func (d *UserDao) UpdateUserPassword(id int, password string) *dingo.ErrorWrap {
	db := global.Orm.Exec("update users set password = ? where id = ?", password, id)
	return dingo.ErrorIf(db.Error, true)
}

// UpdateUserQrcode 更新用户收款二维码
func (d *UserDao) UpdateUserQrcode(id int, qrcode string) *dingo.ErrorWrap {
	db := global.Orm.Exec("update users set wx_income_qrcode = ? where id = ?", qrcode, id)
	return dingo.ErrorIf(db.Error, true)
}

// UpdateUserIsBind 解绑
func (d *UserDao) UpdateUserIsBind(id int) *dingo.ErrorWrap {
	db := global.Orm.Debug().Exec("update users set is_bind = 0 where id = ?", id)
	return dingo.ErrorIf(db.Error, true)
}

// 修改用户类型 商户--> 代理商  代理商-->商户
func (d *UserDao) UpdateUserType(id int, isPlace, isAdmin int) *dingo.ErrorWrap {
	db := global.Orm.Debug().Exec("update users set is_place = ?,set is_admin = ? where id = ?", isPlace, isAdmin, id)
	return dingo.ErrorIf(db.Error, true)
}

// UpdateUserMoney  更新代理商用户金额
func (d *UserDao) UpdateUserMoney(money int64, id int) *dingo.ErrorWrap {
	sql := "update users set money = ? where id = ?"
	db := global.Orm.Exec(sql, money, id)
	return dingo.ErrorIf(db.Error, true)
}

// UpdateUserTotalMoney  更新代理商用户总金额
func (d *UserDao) UpdateUserTotalMoney(money int64, id int) *dingo.ErrorWrap {
	sql := "update users set total_money = ? where id = ?"
	db := global.Orm.Exec(sql, money, id)
	return dingo.ErrorIf(db.Error, true)
}

// UpdateUserDrawMoney  更新代理商用户抽单金额
func (d *UserDao) UpdateUserDrawMoney(money int64, id int) *dingo.ErrorWrap {
	sql := "update users set draw_money = ? where id = ?"
	db := global.Orm.Exec(sql, money, id)
	return dingo.ErrorIf(db.Error, true)
}

// UpdateUserDrawMoney  更新代理商用户登录时间和登录IP
func (d *UserDao) UpdateUserLoginInfo(id int, ip string, t dingo.Time) *dingo.ErrorWrap {
	sql := "update users set last_login_time = ?,last_login_ip = ? where id = ?"
	db := global.Orm.Exec(sql, int(t), ip, id)
	return dingo.ErrorIf(db.Error, true)
}

// UpdateUserDrawMoney  更新代理商用户登录次数
func (d *UserDao) UpdateUserLoginCount(id int) *dingo.ErrorWrap {
	//m := users.New()
	//db := global.Orm.Model(m).
	//	UpdateColumn("login_count", gorm.Expr("login_count + ?", 1))

	sql := "update users set login_count = login_count + ? where id = ?"
	db := global.Orm.Exec(sql, 1, id)
	return dingo.ErrorIf(db.Error, true)
}

// UpdateUserDeleteStatus 更新用户删除状态 软删除
func (d *UserDao) UpdateUserDeleteStatus(id int, status int8) *dingo.ErrorWrap {
	sql := "update users set is_delete = ? where id = ?"
	db := global.Orm.Exec(sql, status, id)
	return dingo.ErrorIf(db.Error, true)
}

// DeleteUser 删除用户
func (d *UserDao) DeleteUser(id int) *dingo.ErrorWrap {
	db := global.Orm.Exec("delete from users where id = ?", id)
	return dingo.ErrorIf(db.Error, true)
}

func (d *UserDao) DeleteStatistical(userId int) *dingo.ErrorWrap {
	db := global.Orm.Exec("delete from agent_income where agent_user_id = ?", userId)

	return dingo.ErrorIf(db.Error, true)
}

// 软删除
func (d *UserDao) DeletePlaceUser(id int) *dingo.ErrorWrap {

	err := global.Orm.Transaction(func(tx *gorm.DB) error {
		placeInfo := placemodel.NewPlaceModel()
		global.Orm.Table("places").Where("id = ?", id).Find(placeInfo)
		m := users.New()
		m.IsDelete = 1
		m.DeleteAt = dingo.Time(time.Now().Unix())
		tx.Debug().Table("users").Select("is_delete", "delete_at").Where("id = ?", placeInfo.UserID).Updates(&m)
		if err := tx.Error; err != nil {
			// 返回任何错误都会回滚事务
			return err
		}

		p := placemodel.NewPlaceModel()
		p.IsDelete = 1
		p.DeleteAt = dingo.Time(time.Now().Unix())
		tx.Debug().Table("places").Select("is_delete", "delete_at").Where("id = ?", placeInfo.Id).Updates(&m)

		if err := tx.Error; err != nil {
			// 返回任何错误都会回滚事务
			return err
		}
		// 返回 nil 提交事务
		return nil
	})

	return dingo.ErrorIf(err, true)
}

// 真实删除
func (d *UserDao) DeleteAllPlaceUser(placeId, userId int) *dingo.ErrorWrap {

	err := global.Orm.Transaction(func(tx *gorm.DB) error {
		p := placemodel.NewPlaceModel()
		tx.Debug().Table("places").Delete(&p, placeId)
		if err := tx.Error; err != nil {
			// 返回任何错误都会回滚事务
			return err
		}

		// 通过用户ID查询，该用户下有商户ID
		userIdArr := []int{userId}
		placeIdArr := NewPlaceDao().GetPlaceIdByUserId(userIdArr).Unwrap().([]int)
		// 用户ID和商户ID 一一匹对时，做联合删除，
		// 如一个用户ID对应多个商户，表明这个用户有其他直属商户，不能做联合删除
		if len(placeIdArr) == 1 {
			u := users.New()
			tx.Debug().Table("users").Delete(&u, userId)

			if err := tx.Error; err != nil {
				// 返回任何错误都会回滚事务
				return err
			}
		}
		// 返回 nil 提交事务
		return nil
	})

	return dingo.ErrorIf(err, true)
}

// 获取用户条数
func (d *UserDao) GetUserCountByopenid(openid string) *dingo.ErrorWrap {
	var count int64
	sql := `select count(1) from users where openid = ?`
	db := global.Orm.Raw(sql, openid).Find(&count)
	return dingo.ErrorIf(db.Error, count)
}

// UpdatePlaceById 更新商户信息
func (d *UserDao) UpdatePlaceUserById(m *users.UserModel) *dingo.ErrorWrap {
	m.UpdateAt = dingo.Time(time.Now().Unix())
	db := global.Orm.Table("users").Where("id = ?", m.ID).Model(&m).Updates(m)
	return dingo.ErrorIf(db.Error, true)
}

func (d *UserDao) UpdateUserById(m *users.UserModel) *dingo.ErrorWrap {
	m.UpdateAt = dingo.Time(time.Now().Unix())
	update := map[string]interface{}{
		"update_at":       m.UpdateAt,
		"login_count":     m.LoginCount,
		"last_login_ip":   m.LastLoginIp,
		"last_login_time": m.LastLoginTime,
	}

	if m.Unionid != "" {
		update["unionid"] = m.Unionid
	}

	db := global.Orm.Table("users").Where("id = ?", m.ID).Updates(update)
	return dingo.ErrorIf(db.Error, true)
}

func (d *UserDao) UpdateUserBindStatus(m *users.UserModel) *dingo.ErrorWrap {
	m.UpdateAt = dingo.Time(time.Now().Unix())
	update := map[string]interface{}{
		"openid":    m.Openid,
		"nick_name": m.NickName,
		"is_bind":   1,
	}

	if m.Unionid != "" {
		update["unionid"] = m.Unionid
	}

	db := global.Orm.Table("users").Where("id = ?", m.ID).Updates(update)
	return dingo.ErrorIf(db.Error, true)
}

func (d *UserDao) InsertWechatUserRelevancy(m *users.UserModel, appid string) *dingo.ErrorWrap {
	if m.Openid == "" || m.Unionid == "" {
		return dingo.ErrorIf(errors.New("openid err"))
	}

	m.UpdateAt = dingo.Time(time.Now().Unix())
	dbInfo := map[string]interface{}{
		"user_id": m.ID,
		"appid":   appid,
		"unionid": m.Unionid,
		"openid":  m.Openid,
	}

	db := global.Orm.Table("wechat_user_relevancy").Create(dbInfo)
	return dingo.ErrorIf(db.Error)
}

// 通过用户ID获取分成信息
func (d *UserDao) GetProfitsByUserId(userId int) *dingo.ErrorWrap {

	lst := make([]*profit.ProfitModel, 0)

	db := global.Orm.Table("profits").Where("user_id = ?", userId).Find(&lst)
	return dingo.ErrorIf(db.Error, lst)
}
func (d *UserDao) GetAgentIsDraw(userId int) (*dingo.ErrorWrap, int64) {
	m := users.New()
	db := global.Orm.Table("users").Where("id = ? and is_draw = 1", userId).Find(&m)
	return dingo.ErrorIf(db.Error, m), db.RowsAffected
}

//查询分公司下的所有网点ID
func (d *UserDao) GetPlacesId(userId int) *dingo.ErrorWrap {
	placesIdArr := make([]int, 0)

	db := global.Orm.Debug().Table("places").Select("id").Where("branch_user_id = ?", userId).Find(&placesIdArr)
	return dingo.ErrorIf(db.Error, placesIdArr)
}
func (d *UserDao) GetPlacesIds(userId int, childUserIds []int) *dingo.ErrorWrap {
	placesIdArr := make([]int, 0)

	db := global.Orm.Debug().Table("places").Select("id").Where("branch_user_id = ? or user_id in (?)", userId, childUserIds).Find(&placesIdArr)
	return dingo.ErrorIf(db.Error, placesIdArr)
}

//查询用户调用验证码次数
func (d *UserDao) GetUserSmsCodeCount(phone string, timeUnix int) *dingo.ErrorWrap {
	var count int64

	db := global.Orm.Debug().Table("sms_code").Select("count(id)").Where("DATE_FORMAT( FROM_UNIXTIME( create_at ), '%Y-%m-%d' ) = DATE_FORMAT( FROM_UNIXTIME( ? ), '%Y-%m-%d' ) and phone = ?", timeUnix, phone).Count(&count)
	return dingo.ErrorIf(db.Error, count)
}

//验证码入库
func (d *UserDao) InsertSmsCode(m *smscode.SmsCode) *dingo.ErrorWrap {
	db := global.Orm.Debug().Table("sms_code").Model(&m).Create(&m)
	if db.Error != nil {
		return dingo.ErrorIf(db.Error, false)
	}
	return dingo.ErrorIf(db.Error, true)
}

//校验验证码是否存在
func (d *UserDao) GetSmsCodeInfo(phone string, code string) *dingo.ErrorWrap {
	var id int
	db := global.Orm.Table("sms_code").Select("id").Where(" phone = ? and code = ? and status = 2", phone, code).Find(&id)

	if id > 0 {
		global.Orm.Table("sms_code").Where(" phone=? and code=?", phone, code).Update("status", 1)
	}
	return dingo.ErrorIf(db.Error, db.RowsAffected)
}

//新增注册用户
func (d *UserDao) InsertRegisterUser(m *users.UserModel) *dingo.ErrorWrap {
	db := global.Orm.Debug().Table("users").Model(&m).Create(&m)
	if db.Error != nil {
		return dingo.ErrorIf(db.Error, false)
	}
	return dingo.ErrorIf(db.Error, true)
}

//查询手机号是否存在
func (d *UserDao) GetPhoneIsExist(phone string) *dingo.ErrorWrap {
	var id int
	db := global.Orm.Debug().Table("users").Select("id").Where(" phone = ? ", phone).Find(&id)
	return dingo.ErrorIf(db.Error, db.RowsAffected)
}

func (d *UserDao) UpdateSmsCode(phone string, code string) *dingo.ErrorWrap {
	//global.Orm.Debug().Table("sms_code").Select("status").Updates()
	//	UPDATE users SET `parent_id` = 1 WHERE  user_id = 1
	log.Println("修改验证码状态：", phone, code)
	db := global.Orm.Debug().Exec("update sms_code set status = 1 where phone = ? and code = ?", phone, code)
	return dingo.ErrorIf(db.Error, true)
}

// GetUserByPlaceId 获取某个用户下的所有代理商用户ID
func (d *UserDao) GetUserNoByPlaceIds(placeIds []int) *dingo.ErrorWrap {
	var userModel []users.UserNoByPlaceIds

	sql := "select (select user_no from users WHERE id = p.user_id) as user_no ,p.id from places p WHERE p.id in(?)"
	db := global.Orm.Debug().Raw(sql, placeIds).Find(&userModel)
	return dingo.ErrorIf(db.Error, userModel)
}

//查询扫码用户
func (d *UserDao) GetScanCodeUser(placeIds []int, date string) *dingo.ErrorWrap {
	var scanCodeUser []users.ScanCodeUser
	sql := `SELECT DATE_FORMAT( FROM_UNIXTIME( create_at ), '%Y-%m-%d' ) date,count(openid) as total_user,place_id FROM orders  
WHERE place_id in(?) and DATE_FORMAT( FROM_UNIXTIME( create_at ), '%Y-%m-%d' ) = ?  GROUP BY place_id`
	db := global.Orm.Debug().Raw(sql, placeIds, date).Find(&scanCodeUser)
	return dingo.ErrorIf(db.Error, scanCodeUser)
}

func (d *UserDao) ExportGetUserList() *dingo.ErrorWrap {
	var userModel []users.UserModel
	db := global.Orm.Debug().Table("users").Find(&userModel)
	return dingo.ErrorIf(db.Error, userModel)
}

func (d *UserDao) LeagueInfoCreate(m *users.CooperationRegister) *dingo.ErrorWrap {
	db := global.Orm.Debug().Table("cooperation_register").Create(&m)
	return dingo.ErrorIf(db.Error, m)
}

//合作登记列表
func (d *UserDao) GetCooperationRegisterList(param *request.CooperationRegisterReq) *dingo.ErrorWrap {
	var (
		lst    []*users.CooperationRegister
		count  int64
		limit  int = param.PageSize
		offset int = param.PageSize * (param.PageNo - 1)
	)

	db := global.Orm.Debug().Table("cooperation_register")

	if param.Phone != "" {
		db.Where("phone = ?", param.Phone)
	}
	if param.Name != "" {
		db.Where("name like ?", fmt.Sprint("%", param.Name, "%"))
	}

	if param.IsAdmin > 0 {
		db.Where("is_admin = ?", param.IsAdmin)
	}

	if param.SelectTime != "" {
		selectTimeArr := strings.Split(param.SelectTime, ",")
		startTime := selectTimeArr[0]
		endTime := selectTimeArr[1]
		db.Where("create_at >= DATE_FORMAT(FROM_UNIXTIME(?),'%Y-%m-%d')", startTime)
		db.Where("create_at <= DATE_FORMAT(FROM_UNIXTIME(?),'%Y-%m-%d')", endTime)
	}

	db.Limit(limit).Offset(offset).Find(&lst).Limit(-1).Offset(-1).Count(&count)
	return dingo.ErrorIf(db.Error, lst, count)
}

//合作登记新增
func (d *UserDao) CreateCooperationRegister(m *users.CooperationRegister) *dingo.ErrorWrap {
	db := global.Orm.Debug().Table("cooperation_register").Create(m)
	return dingo.ErrorIf(db.Error, true)
}

//合作登记修改
func (d *UserDao) UpdateCooperationRegister(m *users.CooperationRegister) *dingo.ErrorWrap {
	db := global.Orm.Debug().Table("cooperation_register").Where("id= ?", m.ID).Model(&m).Updates(m)
	return dingo.ErrorIf(db.Error, true)

}

//合作登记删除
func (d *UserDao) DeleteCooperationRegister(id int) *dingo.ErrorWrap {
	db := global.Orm.Exec("delete from cooperation_register where id = ?", id)
	return dingo.ErrorIf(db.Error, true)
}

// 获取供应商列表
func (d *UserDao) GetMscListByIsAdmin() *dingo.ErrorWrap {
	var lst []*users.UserModel
	db := global.Orm.Debug().Table("users").
		Where("is_admin = ? and is_delete = 0", helper.TypeNumIsAdminMsc)

	db.Order("id desc").Find(&lst)
	return dingo.ErrorIf(db.Error, lst)
}

func (d *UserDao) UpdateUserZfbBind(memberId, userId int, openid string) *dingo.ErrorWrap {
	db := global.Orm.Debug().Exec("update users set member_id = ?,zfb_openid = ? where id = ?", memberId, openid, userId)
	return dingo.ErrorIf(db.Error, true)
}

func (d *UserDao) UpdateUserZfbUnBind(userId int) *dingo.ErrorWrap {
	db := global.Orm.Debug().Exec("update users set member_id = 0,zfb_openid = '' where id = ?", userId)
	return dingo.ErrorIf(db.Error, true)
}